use crate::config::NetworkConfig;
// Raft integration types removed in placeholder mode
use crate::{Error, NodeId, Result};

// use openraft::BasicNode; // Placeholder for future Raft integration
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::info;

/// Network manager that handles node-to-node communication
pub struct NetworkManager {
    config: NetworkConfig,
    connections: Arc<RwLock<HashMap<NodeId, Arc<RaftClient>>>>,
}

impl NetworkManager {
    /// 创建新的网络管理器
    ///
    /// 当前实现为占位: 仅保存配置并初始化连接映射表。
    pub async fn new(config: &NetworkConfig) -> Result<Self> {
        info!("Initializing network manager");

        Ok(Self {
            config: config.clone(),
            connections: Arc::new(RwLock::new(HashMap::new())),
        })
    }

    /// 连接到一个对等节点（并缓存客户端）
    ///
    /// 注意: 目前使用占位 node_id=1，真实实现应在握手/元数据中获得对端 node_id。
    pub async fn connect_to_peer(&self, address: &str) -> Result<()> {
        info!("Connecting to peer: {}", address);

        let client = RaftClient::new(address, &self.config).await?;

        // Store connection for future use
        // Note: In a real implementation, you'd extract the node ID from the connection
        let node_id = 1; // Placeholder
        self.connections
            .write()
            .await
            .insert(node_id, Arc::new(client));

        Ok(())
    }

    /// 创建 Raft 网络抽象（当前仅传递连接映射）
    pub async fn create_raft_network(&self) -> Result<Arc<ClusterNetwork>> {
        Ok(Arc::new(ClusterNetwork::new(self.connections.clone())))
    }

    /// 获取到指定节点的已缓存连接（若存在）
    pub async fn get_connection(&self, node_id: NodeId) -> Option<Arc<RaftClient>> {
        self.connections.read().await.get(&node_id).cloned()
    }

    /// 移除指定节点连接缓存
    pub async fn remove_connection(&self, node_id: NodeId) {
        self.connections.write().await.remove(&node_id);
    }
}

/// Simplified network wrapper (Raft trait implementations removed for now)
pub struct ClusterNetwork {
    connections: Arc<RwLock<HashMap<NodeId, Arc<RaftClient>>>>,
}
impl ClusterNetwork {
    pub fn new(connections: Arc<RwLock<HashMap<NodeId, Arc<RaftClient>>>>) -> Self {
        Self { connections }
    }
}
impl Clone for ClusterNetwork {
    fn clone(&self) -> Self {
        Self {
            connections: self.connections.clone(),
        }
    }
}

/// Raft client for communicating with other nodes
pub struct RaftClient {
    _address: String,
    _client: reqwest::Client,
}

impl RaftClient {
    /// 创建一个新的 Raft HTTP 客户端
    ///
    /// 构建 reqwest::Client 并设置超时时间（解析自配置）。
    pub async fn new(address: &str, config: &NetworkConfig) -> Result<Self> {
        let timeout = parse_duration(&config.connect_timeout)
            .map_err(|e| Error::network(format!("Invalid connect timeout: {}", e)))?;

        let client = reqwest::Client::builder()
            .timeout(timeout)
            .build()
            .map_err(|e| Error::network(format!("Failed to create HTTP client: {}", e)))?;

        Ok(Self {
            _address: address.to_string(),
            _client: client,
        })
    }

    // Raft-specific RPC methods removed in placeholder mode
}

/// 解析带单位的时间字符串 (如 "5s", "10m", "1h", "500ms") -> Duration
/// 支持单位: ns / us / μs / ms / s / m / h
/// 错误: 空字符串 / 无单位 / 非法数字 / 不支持单位 将返回 Error
fn parse_duration(s: &str) -> Result<std::time::Duration> {
    let s = s.trim();

    if s.is_empty() {
        return Err(Error::network("Empty duration string"));
    }

    let (number_part, unit_part) = if let Some(pos) = s.chars().position(|c| c.is_alphabetic()) {
        s.split_at(pos)
    } else {
        return Err(Error::network("Duration must have a unit (s, m, h)"));
    };

    let number: f64 = number_part
        .parse()
        .map_err(|_| Error::network("Invalid number in duration"))?;

    let multiplier = match unit_part {
        "ns" => 1e-9,
        "us" | "μs" => 1e-6,
        "ms" => 1e-3,
        "s" => 1.0,
        "m" => 60.0,
        "h" => 3600.0,
        _ => {
            return Err(Error::network(
                "Invalid duration unit (supported: ns, us, ms, s, m, h)",
            ))
        }
    };

    let seconds = number * multiplier;
    Ok(std::time::Duration::from_secs_f64(seconds))
}

/// Connection pool for managing multiple connections
pub struct ConnectionPool {
    pool: Arc<RwLock<HashMap<String, Arc<RaftClient>>>>,
    config: NetworkConfig,
}

impl ConnectionPool {
    pub fn new(config: NetworkConfig) -> Self {
        Self {
            pool: Arc::new(RwLock::new(HashMap::new())),
            config,
        }
    }

    /// Get or create connection to an address
    pub async fn get_connection(&self, address: &str) -> Result<Arc<RaftClient>> {
        // Check if connection already exists
        {
            let pool = self.pool.read().await;
            if let Some(client) = pool.get(address) {
                return Ok(client.clone());
            }
        }

        // Create new connection
        let client = Arc::new(RaftClient::new(address, &self.config).await?);

        // Store in pool
        {
            let mut pool = self.pool.write().await;
            pool.insert(address.to_string(), client.clone());
        }

        Ok(client)
    }

    /// Remove connection from pool
    pub async fn remove_connection(&self, address: &str) {
        let mut pool = self.pool.write().await;
        pool.remove(address);
    }

    /// Get pool size
    pub async fn size(&self) -> usize {
        self.pool.read().await.len()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_duration() {
        assert_eq!(
            parse_duration("5s").unwrap(),
            std::time::Duration::from_secs(5)
        );
        assert_eq!(
            parse_duration("10m").unwrap(),
            std::time::Duration::from_secs(600)
        );
        assert_eq!(
            parse_duration("1h").unwrap(),
            std::time::Duration::from_secs(3600)
        );
        assert_eq!(
            parse_duration("500ms").unwrap(),
            std::time::Duration::from_millis(500)
        );

        assert!(parse_duration("").is_err());
        assert!(parse_duration("5").is_err());
        assert!(parse_duration("5x").is_err());
    }
}
